package org.hackystat.ambientdevice.trigger;

import java.util.logging.Logger;
import org.hackystat.sensorbase.client.SensorBaseClient;
import org.hackystat.sensorbase.client.SensorBaseClientException;
import org.hackystat.sensorbase.client.SensorBaseClient.InvitationReply;
import org.hackystat.sensorbase.resource.projects.jaxb.Invitations;
import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorDataIndex;
import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorDataRef;
import org.hackystat.utilities.logger.HackystatLogger;
import org.hackystat.utilities.tstamp.Tstamp;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;

/**
 * Provides a helper class to facilitate JUnit testing.
 * 
 * @author Philip Johnson
 */
public class HackystatTriggerTestHelper {

  /** The Sensorbase server used in these tests. */
  protected static org.hackystat.sensorbase.server.Server sensorbaseServer;
  /** The DPS server used in these tests. */
  protected static org.hackystat.dailyprojectdata.server.Server dailyProjectDataServer;
  /** The tester for this test case. */
  protected String tester = "TriggerTester@hackystat.org";
  /** The user for this test case. */
  protected String user = "TestUser@hackystat.org";
  /** The project owner for this test case. */
  protected String projectOwner = "TestProjectOwner@hackystat.org";
  /** The name of the test project. */
  protected String projectName = "TestProject";
  /** SensorBase Client for the tester. */
  SensorBaseClient testClient;
  /** SensorBase Client for the owner. */
  SensorBaseClient ownerClient;
  /** SensorBase Client for the project owner. */
  SensorBaseClient userClient;
  /** The logger for logging. */
  protected Logger logger = HackystatLogger.getLogger("org.hackystat.ambientdevice");

  /**
   * Constructor.
   */
  public HackystatTriggerTestHelper() {
    HackystatLogger.setLoggingLevel(logger, "FINEST");
  }

  /**
   * Starts the server going for these tests.
   * 
   * @throws Exception If problems occur setting up the server.
   */
  @BeforeClass
  public static void setupServer() throws Exception {
    // Create a testing version of the Sensorbase.
    HackystatTriggerTestHelper.sensorbaseServer = org.hackystat.sensorbase.server.Server
        .newTestInstance();
    HackystatTriggerTestHelper.dailyProjectDataServer = org.hackystat.dailyprojectdata.server.Server
        .newTestInstance();
  }

  /**
   * Prepare the test users and project for the tests.
   * @throws SensorBaseClientException when error encountered.
   */
  @Before
  public void setUp() throws SensorBaseClientException {

    SensorBaseClient.registerUser(getSensorBaseHostName(), tester);
    testClient = new SensorBaseClient(getSensorBaseHostName(), tester, tester);
    testClient.authenticate();
    SensorBaseClient.registerUser(getSensorBaseHostName(), projectOwner);
    ownerClient = new SensorBaseClient(getSensorBaseHostName(), projectOwner, projectOwner);
    ownerClient.authenticate();
    SensorBaseClient.registerUser(getSensorBaseHostName(), user);
    userClient = new SensorBaseClient(getSensorBaseHostName(), user, user);
    userClient.authenticate();

    // prepare a project instance to provide the server information.
    org.hackystat.sensorbase.resource.projects.jaxb.Project hackystatProject = 
      new org.hackystat.sensorbase.resource.projects.jaxb.Project();
    hackystatProject.setOwner(projectOwner);
    hackystatProject.setName(projectName);
    Invitations invitations = new Invitations();
    invitations.getInvitation().add(tester);
    invitations.getInvitation().add(user);
    hackystatProject.setInvitations(invitations);
    hackystatProject.setStartTime(Tstamp.incrementDays(Tstamp.makeTimestamp(),-1));
    hackystatProject.setEndTime(Tstamp.incrementDays(Tstamp.makeTimestamp(), 1));
    
    // put a new project to sensorbase.
    ownerClient.putProject(hackystatProject);
    testClient.reply(projectOwner, projectName, InvitationReply.ACCEPT);
    userClient.reply(projectOwner, projectName, InvitationReply.ACCEPT);
    
  }
  
  /**
   * Clean up data when tests are done.
   * @throws SensorBaseClientException when error encountered.
   */
  @After 
  public void cleanUp() throws SensorBaseClientException {
    // First, delete all sensor data sent by the tester.
    SensorDataIndex index = testClient.getSensorDataIndex(tester);
    for (SensorDataRef ref : index.getSensorDataRef()) {
      testClient.deleteSensorData(tester, ref.getTimestamp());
    }
    // Second, delete all sensor data sent by the user.
    index = userClient.getSensorDataIndex(user);
    for (SensorDataRef ref : index.getSensorDataRef()) {
      userClient.deleteSensorData(user, ref.getTimestamp());
    }
    // Third, delete all sensor data sent by the project owner.
    index = ownerClient.getSensorDataIndex(projectOwner);
    for (SensorDataRef ref : index.getSensorDataRef()) {
      ownerClient.deleteSensorData(projectOwner, ref.getTimestamp());
    }
    // Then, delete the project.
    ownerClient.deleteProject(projectOwner, projectName);
    // Now delete the users too.
    testClient.deleteUser(tester);
    userClient.deleteUser(user);
    ownerClient.deleteUser(projectOwner);
  }
  
  /**
   * Returns the hostname associated with this DPD test server.
   * 
   * @return The host name, including the context root.
   */
  protected String getDailyProjectDataHostName() {
    return HackystatTriggerTestHelper.dailyProjectDataServer.getHostName();
  }

  /**
   * Returns the sensorbase hostname that this DPD server communicates with.
   * 
   * @return The host name, including the context root.
   */
  protected String getSensorBaseHostName() {
    return HackystatTriggerTestHelper.sensorbaseServer.getServerProperties().getFullHost();
  }
}
